'''
定义一个期权的类，包含：
底层标的合约、期权行权价步长、期权到期日
'''
import datetime


class Spec:
    # 定义父类 列表内容格式：[symbol, contracts, type(EU or AM?), price_range based on last day settle price]
    name_dict_shfe = {
        "沪金": ["AU", ['L'], "EU"],
        "沪铜": ["CU", ['L'], "EU"],
        "橡胶": ["RU", ['01', '05', '09'], "AM"]
    }
    name_dict_czce = {
        "甲醇": ["MA", ['01', '05', '09'], "AM"],
        "PTA": ["TA", ['01', '05', '09'], "AM"],
        "白糖": ["SR", ['01', '05', '09'], "AM"],
        "棉花": ["CF", ['01', '05', '09'], "AM"],
        "菜粕": ["RM", ['01', '05', '09'], "AM"],
        "动力煤": ["ZC", ['01', '05', '09'], "AM"]
    }
    name_dict_dce = {
        "铁矿石": ["I", ['01', '05', '09'], "AM"],
        "豆粕": ["M", ['01', '05', '09'], "AM"],
        "LPG": ["PG", ['L'], "AM"],
        "玉米": ["C", ['01', '05', '09'], "AM"],
        "PE": ["L", ['01', '05', '09'], "AM"],
        "PP": ["PP", ['01', '05', '09'], "AM"],
        "PVC": ["V", ['01', '05', '09'], "AM"]
    }
    name_dict = {**name_dict_shfe, **name_dict_dce, **name_dict_czce}
    namelist_shfe = list(name_dict_shfe.keys())
    namelist_czce = list(name_dict_czce.keys())
    namelist_dce = list(name_dict_dce.keys())
    namelist = list(name_dict.keys())
    symblist = [x[0] for x in list(name_dict.values())]

    def __init__(self, name):
        self.name = name
        self.symbol = self.name_dict[name][0]
        self.type = self.name_dict[name][2]

    @property
    def opt_exchange(self):
        name = self.name
        if name in list(self.name_dict_czce.keys()):
            return 'CZCE'
        elif name in list(self.name_dict_dce.keys()):
            return 'DCE'
        elif name in list(self.name_dict_shfe.keys()):
            return 'SHFE'
        else:
            return False

    @property
    def raw_codes(self):
        name = self.name
        contract_series = self.name_dict[name][1]
        current_date = datetime.datetime.now()
        if len(contract_series) == 1:
            if name == 'LPG':
                codes = ['PG2011', 'PG2012', 'PG2101']  # 目前的LPG合约不规则，先用固定合约，后续再改
            elif current_date.month <= 9:
                code1 = self.symbol + str(int(current_date.strftime("%y%m")) + 1)
                code2 = self.symbol + str(int(current_date.strftime("%y%m")) + 2)
                code3 = self.symbol + str(int(current_date.strftime("%y%m")) + 3)
                codes = [code1, code2, code3]
            else:
                delta = 12 - current_date.month
                deltalist = list(range(delta))
                codes_front = []
                for i in deltalist:
                    code = self.symbol + str(int(current_date.strftime("%y%m")) + i + 1)
                    codes_front.append(code)
                remainlist = list(range(3 - delta))
                codes_end = []
                for i in remainlist:
                    code = self.symbol + str(current_date.year + 1)[2:] + "0" + str(i + 1)
                    codes_end.append(code)
                codes = codes_front + codes_end
            return codes
        elif len(contract_series) == 2:
            if current_date.month < int(contract_series[0]):
                code1 = self.symbol + str(current_date.year)[2:] + contract_series[0]
                code2 = self.symbol + str(current_date.year)[2:] + contract_series[1]
                code3 = self.symbol + str(current_date.year + 1)[2:] + contract_series[0]
            elif int(contract_series[0]) <= current_date.month < int(contract_series[1]):
                code1 = self.symbol + str(current_date.year)[2:] + contract_series[1]
                code2 = self.symbol + str(current_date.year + 1)[2:] + contract_series[0]
                code3 = self.symbol + str(current_date.year + 1)[2:] + contract_series[1]
            else:
                code1 = self.symbol + str(current_date.year + 1)[2:] + contract_series[0]
                code2 = self.symbol + str(current_date.year + 1)[2:] + contract_series[1]
                code3 = self.symbol + str(current_date.year + 2)[2:] + contract_series[0]
            return [code1, code2, code3]
        elif len(contract_series) == 3:
            if current_date.month < int(contract_series[1]):
                code1 = self.symbol + str(current_date.year)[2:] + contract_series[1]
                code2 = self.symbol + str(current_date.year)[2:] + contract_series[2]
                code3 = self.symbol + str(current_date.year + 1)[2:] + contract_series[0]
            elif int(contract_series[1]) <= current_date.month < int(contract_series[2]):
                code1 = self.symbol + str(current_date.year)[2:] + contract_series[2]
                code2 = self.symbol + str(current_date.year + 1)[2:] + contract_series[0]
                code3 = self.symbol + str(current_date.year + 1)[2:] + contract_series[1]
            else:
                code1 = self.symbol + str(current_date.year + 1)[2:] + contract_series[0]
                code2 = self.symbol + str(current_date.year + 1)[2:] + contract_series[1]
                code3 = self.symbol + str(current_date.year + 1)[2:] + contract_series[2]
            return [code1, code2, code3]

    @property
    def underlying_codes(self):
        # 给出标的合约代码
        codes = self.raw_codes[:2]          # 主力+次主力合约
        series = []
        for x in codes:
            if self.opt_exchange == "SHFE":
                code = "SHFE.{}".format(x.lower())
            elif self.opt_exchange == "DCE":
                code = "DCE.{}".format(x.lower())
            elif self.opt_exchange == "CZCE":
                x = x.replace(x[-4], "")
                code = "CZCE.{}".format(x.upper())
            else:
                code = False
            series.append(code)
        return series

    @property
    def opt_codes_adapter(self):
        # 给出期权代码的模板
        if self.opt_exchange == "DCE":
            adapter = ["-C-", "-P-"]
        elif self.opt_exchange == "SHFE" or "CZCE":
            adapter = ["C", "P"]
        else:
            adapter = False
        return adapter
# DCE.m1807-C-2450 - 大商所豆粕期权
# CZCE.CF003C11000 - 郑商所棉花期权
# SHFE.au2004C308 - 上期所黄金期权


class AU(Spec):
    # 定义沪金子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 1

    @property
    def pace(self):
        if self.price <= 200:
            pace = 2
        elif 200 < self.price <= 400:
            pace = 4
        else:
            pace = 8
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class CU(Spec):
    # 定义沪铜子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1
        self.type = 1

    @property
    def pace(self):
        if self.price <= 40000:
            pace = 500
        elif 40000 < self.price <= 80000:
            pace = 1000
        else:
            pace = 2000
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class RU(Spec):
    # 定义橡胶子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 2

    @property
    def pace(self):
        if self.price <= 10000:
            pace = 100
        elif 10000 < self.price <= 25000:
            pace = 250
        else:
            pace = 500
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class I(Spec):
    # 定义铁矿子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 2

    @property
    def pace(self):
        if self.price <= 300:
            pace = 5
        elif 300 < self.price <= 1000:
            pace = 10
        else:
            pace = 20
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class M(Spec):
    # 定义豆粕子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 2

    @property
    def pace(self):
        if self.price <= 2000:
            pace = 25
        elif 2000 < self.price <= 5000:
            pace = 50
        else:
            pace = 100
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class C(Spec):
    # 定义玉米子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 2

    @property
    def pace(self):
        if self.price <= 1000:
            pace = 10
        elif 1000 < self.price <= 3000:
            pace = 20
        else:
            pace = 40
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class PG(Spec):
    # 定义LPG子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 2

    @property
    def pace(self):
        if self.price <= 2000:
            pace = 25
        elif 2000 < self.price <= 6000:
            pace = 50
        else:
            pace = 100
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class L(Spec):
    # 定义PE子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 2

    @property
    def pace(self):
        if self.price <= 5000:
            pace = 50
        elif 5000 < self.price <= 10000:
            pace = 100
        else:
            pace = 200
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class PP(Spec):
    # 定义PP子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 2

    @property
    def pace(self):
        if self.price <= 5000:
            pace = 50
        elif 5000 < self.price <= 10000:
            pace = 100
        else:
            pace = 200
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class V(Spec):
    # 定义PVC子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = 1.5
        self.type = 2

    @property
    def pace(self):
        if self.price <= 5000:
            pace = 50
        elif 5000 < self.price <= 10000:
            pace = 100
        else:
            pace = 200
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class SR(Spec):
    # 定义白糖子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = [5, 1, 5]
        self.type = 2

    @property
    def pace(self):
        if self.price <= 3000:
            pace = 50
        elif 3000 < self.price <= 10000:
            pace = 100
        else:
            pace = 200
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class CF(Spec):
    # 定义棉花子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = [6, 1, 6]
        self.type = 2

    @property
    def pace(self):
        if self.price <= 10000:
            pace = 100
        elif 10000 < self.price <= 20000:
            pace = 200
        else:
            pace = 400
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class TA(Spec):
    # 定义PTA子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = [6, 1, 6]
        self.type = 2

    @property
    def pace(self):
        if self.price <= 5000:
            pace = 50
        elif 5000 < self.price <= 10000:
            pace = 100
        else:
            pace = 200
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class MA(Spec):
    # 定义甲醇子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = [6, 1, 6]
        self.type = 2

    @property
    def pace(self):
        if self.price <= 2500:
            pace = 25
        elif 2500 < self.price <= 5000:
            pace = 50
        else:
            pace = 100
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm


class RM(Spec):
    # 定义菜粕子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = [6, 1, 6]
        self.type = 2

    @property
    def pace(self):
        if self.price <= 2500:
            pace = 25
        elif 2500 < self.price <= 5000:
            pace = 50
        else:
            pace = 100
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm

class ZC(Spec):
    # 定义动力煤子类
    def __init__(self, name, price):
        super().__init__(name)
        self.price = price
        self.p_range = [6, 1, 6]
        self.type = 2

    @property
    def pace(self):
        if self.price <= 500:
            pace = 5
        else:
            pace = 10
        return pace

    @property
    def atm(self):
        price = self.price
        pace = self.pace
        mod = price % pace
        if mod < pace / 2:
            atm = price - mod
        else:
            atm = price - mod + pace
        return atm